package org.luxor.commons.sms.client.aliyun;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.luxor.commons.core.utils.Jackson2Utils;
import org.luxor.commons.sms.client.AbstractSmsClient;
import org.luxor.commons.sms.config.properies.AliyunProperties;
import org.luxor.commons.sms.constant.CountryCode;
import org.luxor.commons.sms.entity.PhoneNumber;
import org.luxor.commons.sms.exception.SmsServiceExection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;


/**
 * 阿里云 短信服务
 *
 * @author Mr.yan @date 2020/2/8
 */
public class AliyunSmsClient extends AbstractSmsClient {
    private static final Logger logger = LoggerFactory.getLogger(AliyunSmsClient.class);
    private static final String SEND_SUCCESS = "OK";

    /**
     * 阿里云 全局配置项
     */
    private final AliyunProperties properties;

    private IAcsClient client;

    public AliyunSmsClient(AliyunProperties properties) {
        this.properties = properties;
        if (this.isEnabled()) {
            this.init();
        }
    }

    private void init() {
        logger.info("Initialization Aliyun open ( Running Aliyun Connector)");
        try {
            DefaultProfile profile = DefaultProfile.getProfile(properties.getRegionId(),
                    properties.getAccessKeyId(), properties.getAccessKeySecret());

            client = new DefaultAcsClient(profile);
            logger.info("Initialize Aliyun Connector Success,bye");
        } catch (Throwable e) {
            logger.error("Initialize Aliyun Connector Failure!", e);
            throw e;
        }
    }

    @Override
    public boolean isEnabled() {
        return properties.isEnabled();
    }

    @Override
    public void sendMessage(Set<PhoneNumber> phoneNumbers, String templateCode, Map<String, String> context, String sender) {
        if (!this.isEnabled()) {
            logger.error("[未开启] 阿里云短信发送功能");
            throw new SmsServiceExection("[未开启] 阿里云短信发送功能");
        }
        if (phoneNumbers == null || phoneNumbers.isEmpty()) {
            return;
        }
        StringJoiner phoneNumberSet = new StringJoiner(",");
        phoneNumbers.forEach(el -> {
            if (CountryCode.China == el.getCountryCode()) {
                phoneNumberSet.add(el.getMobile());
            } else {
                phoneNumberSet.add(el.getCountryCode().getCode() + el.getMobile());
            }
        });

        try {
            logger.debug("阿里云短信发送开始... 接收手机号:{} / 短信模板Code:{} / 发送人:{}", phoneNumbers, templateCode, sender);

            CommonRequest request = new CommonRequest();
            request.setSysMethod(MethodType.POST);
            request.setSysDomain(properties.getDomain());
            request.setSysVersion("2017-05-25");
            request.setSysAction("SendSms");
            request.putQueryParameter("RegionId", properties.getRegionId());
            request.putQueryParameter("PhoneNumbers", phoneNumberSet.toString());
            request.putQueryParameter("SignName", properties.getSignName());
            request.putQueryParameter("TemplateCode", templateCode);
            if (context != null) {
                request.putQueryParameter("TemplateParam", Jackson2Utils.toJson(context));
            }
            // 批量发送短信
            CommonResponse response = client.getCommonResponse(request);
            // 检查响应结果中发送失败的记录
            checkSendException(response);
            Map<String, String> responseAsMap = Jackson2Utils.toMap(response.getData(), String.class);
            logger.debug("阿里云短信发送完成, server requestId: {}", responseAsMap.get("RequestId"));
        } catch (Exception e) {
            logger.error("阿里云短信发送失败，请核对阿里云配置信息", e);
            throw new SmsServiceExection("阿里云短信发送失败，请核对阿里云配置信息", e);
        }
    }

    private void checkSendException(CommonResponse response) {
        if (response == null || response.getHttpStatus() != 200 || response.getData() == null) {
            throw new SmsServiceExection("阿里云短信发送失败，服务器没有正常响应");
        }
        Map<String, String> responseAsMap = Jackson2Utils.toMap(response.getData(), String.class);
        if (!SEND_SUCCESS.equalsIgnoreCase(responseAsMap.getOrDefault("Code", "failure"))) {
            logger.error("阿里云短信发送失败, 详情反馈:{}", response.getData());
            throw new SmsServiceExection(-1, "阿里云短信发送失败", response.getData());
        }
    }

}
